#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#include <chrono>
#include <ctime>
#include <memory>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>

const int UPDATE_INTERVAL = 30; // 路由更新间隔(秒)
const int TIMEOUT = 180;        // 路由超时时间(秒)
const int GARBAGE_COLLECTION = 120; // 垃圾收集时间(秒)
const int MAX_HOP_COUNT = 15;   // RIP最大跳数
const int BUFFER_SIZE = 1024;   // 缓冲区大小

// 路由表项结构
struct RouteEntry {
    std::string destination;    // 目的网络
    std::string nextHop;        // 下一跳
    int cost;                   // 代价
    time_t lastUpdate;          // 最后更新时间
    bool markedForDeletion;     // 是否标记为删除
    
    RouteEntry() : cost(MAX_HOP_COUNT + 1), lastUpdate(time(nullptr)), markedForDeletion(false) {}
};

// RIP数据包结构
struct RIPPacket {
    char command;           // 命令(1=请求, 2=响应)
    char version;           // 版本(通常为2)
    short zero;             // 保留字段
    std::vector<std::pair<std::string, int>> entries; // 路由项(目的网络, 代价)
};

class RIPNode {
private:
    std::string nodeId;                // 节点ID
    int port;                          // 监听端口
    std::map<std::string, int> neighbors; // 邻居表(邻居ID, 直接链路代价)
    std::map<std::string, RouteEntry> routingTable; // 路由表
    std::mutex tableMutex;             // 保护路由表的互斥锁
    bool running;                      // 运行标志
    int socketFd;                      // UDP套接字

public:
    RIPNode(const std::string& id, int portNum) 
        : nodeId(id), port(portNum), running(true) {
        // 初始化套接字
        socketFd = socket(AF_INET, SOCK_DGRAM, 0);
        if (socketFd < 0) {
            std::cerr << "创建套接字失败" << std::endl;
            exit(1);
        }

        // 绑定地址和端口
        sockaddr_in serverAddr{};
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_addr.s_addr = INADDR_ANY;
        serverAddr.sin_port = htons(port);

        if (bind(socketFd, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr)) < 0) {
            std::cerr << "绑定套接字失败" << std::endl;
            exit(1);
        }

        // 添加自己的路由表项
        RouteEntry selfEntry;
        selfEntry.destination = nodeId;
        selfEntry.nextHop = nodeId;
        selfEntry.cost = 0;
        routingTable[nodeId] = selfEntry;
    }

    ~RIPNode() {
        close(socketFd);
    }

    // 添加邻居
    void addNeighbor(const std::string& neighborId, int cost) {
        neighbors[neighborId] = cost;
        
        // 初始化邻居的路由表项
        RouteEntry entry;
        entry.destination = neighborId;
        entry.nextHop = neighborId;
        entry.cost = cost;
        routingTable[neighborId] = entry;
        
        std::cout << "添加邻居: " << neighborId << " 代价: " << cost << std::endl;
    }

    // 启动RIP节点
    void start() {
        // 启动接收线程
        std::thread receiveThread(&RIPNode::receiveUpdates, this);
        
        // 启动定期更新线程
        std::thread updateThread(&RIPNode::sendUpdatesPeriodically, this);
        
        // 启动超时检查线程
        std::thread timeoutThread(&RIPNode::checkTimeouts, this);
        
        // 主线程显示路由表
        displayRoutingTablePeriodically();
        
        // 等待线程结束
        receiveThread.join();
        updateThread.join();
        timeoutThread.join();
    }

    // 停止RIP节点
    void stop() {
        running = false;
    }

private:
    // 接收路由更新
    void receiveUpdates() {
        sockaddr_in clientAddr{};
        socklen_t clientAddrLen = sizeof(clientAddr);
        char buffer[BUFFER_SIZE];

        while (running) {
            memset(buffer, 0, BUFFER_SIZE);
            int bytesRead = recvfrom(socketFd, buffer, BUFFER_SIZE, 0, 
                                    reinterpret_cast<sockaddr*>(&clientAddr), &clientAddrLen);
            
            if (bytesRead > 0) {
                std::string senderIp = inet_ntoa(clientAddr.sin_addr);
                int senderPort = ntohs(clientAddr.sin_port);
                
                // 解析RIP数据包
                RIPPacket packet = parseRIPPacket(buffer, bytesRead);
                
                // 处理路由更新
                if (packet.command == 2) { // 响应包
                    std::string senderId = getNodeIdFromAddress(senderIp, senderPort);
                    processRoutingUpdate(senderId, packet);
                }
            }
        }
    }

    // 解析RIP数据包
    RIPPacket parseRIPPacket(const char* buffer, int length) {
        RIPPacket packet;
        packet.command = buffer[0];
        packet.version = buffer[1];
        packet.zero = ntohs(*reinterpret_cast<const short*>(&buffer[2]));
        
        // 解析路由项
        int offset = 4;
        while (offset + 20 <= length) { // 每个路由项20字节
            std::string destination = std::string(buffer + offset + 4, 16); // 假设目的地址为字符串
            int cost = ntohl(*reinterpret_cast<const int*>(&buffer[offset + 16]));
            packet.entries.emplace_back(destination, cost);
            offset += 20;
        }
        
        return packet;
    }

    // 根据IP和端口获取节点ID
    std::string getNodeIdFromAddress(const std::string& ip, int port) {
        // 简化实现，实际中应使用映射表或其他机制
        for (const auto& neighbor : neighbors) {
            // 这里只是示例，实际需要更复杂的映射逻辑
            if (neighbor.first.find(std::to_string(port)) != std::string::npos) {
                return neighbor.first;
            }
        }
        return "unknown";
    }

    // 处理路由更新
    void processRoutingUpdate(const std::string& senderId, const RIPPacket& packet) {
        std::lock_guard<std::mutex> lock(tableMutex);
        
        bool tableChanged = false;
        
        std::cout << "收到来自 " << senderId << " 的路由更新" << std::endl;
        
        // 获取到发送者的当前代价
        int senderCost = (routingTable.find(senderId) != routingTable.end()) 
                         ? routingTable[senderId].cost : MAX_HOP_COUNT + 1;
        
        // 处理每个路由项
        for (const auto& entry : packet.entries) {
            std::string destination = entry.first;
            int advertisedCost = entry.second;
            
            // 忽略自身
            if (destination == nodeId) continue;
            
            // 计算新的代价
            int newCost = senderCost + advertisedCost;
            if (newCost > MAX_HOP_COUNT) newCost = MAX_HOP_COUNT + 1;
            
            // 如果是新的目的地，或者找到更短的路径，或者从相同下一跳收到更新
            if (routingTable.find(destination) == routingTable.end() ||
                newCost < routingTable[destination].cost ||
                (routingTable[destination].nextHop == senderId && advertisedCost != routingTable[destination].cost)) {
                
                // 毒性逆转：如果通过senderId到达destination的路径是通过senderId，则不更新
                if (routingTable.find(destination) != routingTable.end() &&
                    routingTable[destination].nextHop == senderId &&
                    advertisedCost >= MAX_HOP_COUNT) {
                    routingTable[destination].cost = MAX_HOP_COUNT + 1;
                    routingTable[destination].markedForDeletion = true;
                } else {
                    routingTable[destination].destination = destination;
                    routingTable[destination].nextHop = senderId;
                    routingTable[destination].cost = newCost;
                    routingTable[destination].lastUpdate = time(nullptr);
                    routingTable[destination].markedForDeletion = false;
                }
                
                tableChanged = true;
                std::cout << "路由表更新: 目的网络=" << destination 
                          << ", 下一跳=" << senderId 
                          << ", 代价=" << newCost << std::endl;
            }
        }
        
        if (tableChanged) {
            displayRoutingTable();
        }
    }

    // 定期发送路由更新
    void sendUpdatesPeriodically() {
        while (running) {
            std::this_thread::sleep_for(std::chrono::seconds(UPDATE_INTERVAL));
            sendRoutingUpdates();
        }
    }

    // 发送路由更新
    void sendRoutingUpdates() {
        std::lock_guard<std::mutex> lock(tableMutex);
        
        std::cout << "发送路由更新..." << std::endl;
        
        // 为每个邻居创建RIP数据包
        for (const auto& neighbor : neighbors) {
            std::string neighborId = neighbor.first;
            int neighborCost = neighbor.second;
            
            RIPPacket packet;
            packet.command = 2; // 响应
            packet.version = 2;
            
            // 构建路由项(带毒性逆转的水平分割)
            for (const auto& entry : routingTable) {
                std::string destination = entry.first;
                const RouteEntry& route = entry.second;
                
                // 不发送回环路由
                if (destination == nodeId) continue;
                
                // 毒性逆转：如果下一跳是邻居，则发送无穷大代价
                int advertisedCost = (route.nextHop == neighborId) ? MAX_HOP_COUNT + 1 : route.cost;
                
                packet.entries.emplace_back(destination, advertisedCost);
            }
            
            // 发送数据包
            sendRIPPacket(neighborId, packet);
        }
    }

    // 发送RIP数据包
    void sendRIPPacket(const std::string& neighborId, const RIPPacket& packet) {
        // 简化实现，实际中需要根据邻居ID获取IP和端口
        sockaddr_in neighborAddr{};
        neighborAddr.sin_family = AF_INET;
        neighborAddr.sin_port = htons(520); // RIP默认端口
        
        // 这里应该根据邻居ID查找实际的IP地址
        inet_pton(AF_INET, "127.0.0.1", &neighborAddr.sin_addr);
        
        // 构建数据包
        char buffer[BUFFER_SIZE];
        memset(buffer, 0, BUFFER_SIZE);
        
        buffer[0] = packet.command;
        buffer[1] = packet.version;
        *reinterpret_cast<short*>(&buffer[2]) = htons(packet.zero);
        
        int offset = 4;
        for (const auto& entry : packet.entries) {
            // 简化的路由项格式
            memset(&buffer[offset], 0, 20);
            memcpy(&buffer[offset + 4], entry.first.c_str(), std::min(16ul, entry.first.length()));
            *reinterpret_cast<int*>(&buffer[offset + 16]) = htonl(entry.second);
            offset += 20;
        }
        
        // 发送数据包
        sendto(socketFd, buffer, offset, 0, 
               reinterpret_cast<sockaddr*>(&neighborAddr), sizeof(neighborAddr));
    }

    // 检查超时的路由
    void checkTimeouts() {
        while (running) {
            std::this_thread::sleep_for(std::chrono::seconds(5));
            
            std::lock_guard<std::mutex> lock(tableMutex);
            time_t currentTime = time(nullptr);
            bool tableChanged = false;
            
            for (auto& entry : routingTable) {
                RouteEntry& route = entry.second;
                
                // 跳过自身
                if (route.destination == nodeId) continue;
                
                // 检查超时
                if (currentTime - route.lastUpdate > TIMEOUT) {
                    if (!route.markedForDeletion) {
                        // 标记为删除
                        route.cost = MAX_HOP_COUNT + 1;
                        route.markedForDeletion = true;
                        route.lastUpdate = currentTime;
                        tableChanged = true;
                        std::cout << "路由超时: " << route.destination << std::endl;
                    } else if (currentTime - route.lastUpdate > TIMEOUT + GARBAGE_COLLECTION) {
                        // 从路由表中删除
                        routingTable.erase(entry.first);
                        tableChanged = true;
                        std::cout << "从路由表中删除: " << route.destination << std::endl;
                    }
                }
            }
            
            if (tableChanged) {
                displayRoutingTable();
            }
        }
    }

    // 定期显示路由表
    void displayRoutingTablePeriodically() {
        while (running) {
            std::this_thread::sleep_for(std::chrono::seconds(10));
            displayRoutingTable();
        }
    }

    // 显示当前路由表
    void displayRoutingTable() {
        std::lock_guard<std::mutex> lock(tableMutex);
        
        std::cout << "\n=== 节点 " << nodeId << " 的路由表 ===" << std::endl;
        std::cout << "目的网络\t下一跳\t\t代价\t最后更新时间" << std::endl;
        
        time_t currentTime = time(nullptr);
        
        for (const auto& entry : routingTable) {
            const RouteEntry& route = entry.second;
            char timeStr[26];
            ctime_r(&route.lastUpdate, timeStr);
            timeStr[24] = '\0'; // 去掉换行符
            
            std::cout << route.destination << "\t\t"
                      << route.nextHop << "\t\t"
                      << (route.cost > MAX_HOP_COUNT ? "无穷大" : std::to_string(route.cost)) << "\t"
                      << timeStr << std::endl;
        }
        
        std::cout << "==========================\n" << std::endl;
    }
};

int main() {
    // 创建RIP节点
    RIPNode node("A", 5200);
    
    // 添加邻居
    node.addNeighbor("B", 1);
    node.addNeighbor("C", 3);
    
    // 启动节点
    node.start();
    
    return 0;
}  